package com.shenlan.project

import ch.ethz.ssh2.Connection
import ch.ethz.ssh2.Session
import ch.ethz.ssh2.StreamGobbler
import com.clickhouse.jdbc.ClickHouseConnection
import com.clickhouse.jdbc.ClickHouseDataSource
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.ObjectWriter
import com.fasterxml.jackson.databind.SerializationFeature
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.*
import java.text.SimpleDateFormat
import java.util.*

open class CustomObjectMapper : ObjectMapper() {
    init {
        //设置日期转换yyyy-MM-dd HH:mm:ss
        dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
        disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
        setSerializationInclusion(JsonInclude.Include.NON_NULL)
    }
}

object ExecUtil {
    // 登录， host 远程主机IP, username 用户名 password 密码 端口默认为22
    @Throws(IOException::class)
    private fun login(host: String, username: String, password: String): Connection {
        val conn = Connection(host)
        conn.connect()
        if (!conn.authenticateWithPassword(username, password)) {
            throw RuntimeException("用户名或密码错误!")
        }
        return conn
    }

    // 执行远程linux命令行
    @Throws(IOException::class)
    fun remoteExec(cmd: String?, host: String, username: String, password: String): String {
        //登录，获取连接
        val conn: Connection = login(host, username, password)
        var session: Session? = null
        var br: BufferedReader? = null
        var out: InputStream? = null
        val res = StringBuffer()
        try {
            // 开启会话
            session = conn.openSession()
            // 执行命令
            session.execCommand(cmd, "UTF-8")
            // 处理输出内容
            var t = session.getStdout()
            out = StreamGobbler(t)
            br = BufferedReader(InputStreamReader(out))
            var line: String?
            while (br.readLine().also { line = it } != null) {
                res.append(line)
                res.append("\r\n")
            }
        } finally {
            //关闭资源
            try {
                out?.close()
                br?.close()
                if (session != null) {
                    session.close()
                }
                if (conn != null) {
                    conn.close()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        return res.toString()
    }

    //返回list
    @Throws(IOException::class)
    fun remoteExecReturnList(cmd: String?, host: String, username: String, password: String): List<String> {
        //登录，获取连接
        val conn: Connection = login(host, username, password)
        var session: Session? = null
        var br: BufferedReader? = null
        var out: InputStream? = null
        var result = mutableListOf<String>()

        try {
            // 开启会话
            session = conn.openSession()
            // 执行命令
            session.execCommand(cmd, "UTF-8")
            // 处理输出内容
            var t = session.getStdout()
            out = StreamGobbler(t)
            br = BufferedReader(InputStreamReader(out))
            var line: String?

            while (br.readLine().also { line = it } != null) {

                line?.let { result.add(it) }

            }
        } finally {
            //关闭资源
            try {
                out?.close()
                br?.close()
                if (session != null) {
                    session.close()
                }
                if (conn != null) {
                    conn.close()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        return result
    }

    //返回 每行 空格切割，并去除空值的 list<List<String>>
    fun remoteExecReturnLists(cmd: String?, host: String, username: String, password: String): List<List<String>> {
        var listResult = mutableListOf<List<String>>()
        var result = remoteExecReturnList(cmd, host, username, password)
        result.forEach {
            var lines = it.split(" ")
            var fList = lines.filter { it.trim().isNotEmpty() }
            listResult.add(fList)
        }

        return listResult

    }

    /**
     * 执行本机linux命令行，与ganymed-ssh2依赖无关，JDK自带功能
     */
    fun exec(command: String?): String {
        val osName = System.getProperty("os.name")
        return try {
            /*系统命令不支持的操作系统Windows XP, 2000 2003 7 8 9 10 11*/
            if (osName.toLowerCase(Locale.ROOT).indexOf("win") != -1) {
                throw RuntimeException("不支持的操作系统:$osName")
            }
            val rt = Runtime.getRuntime()
            val process = rt.exec(command)
            val br = LineNumberReader(
                InputStreamReader(
                    process.inputStream
                )
            )
            val sb = StringBuffer()
            var line: String?
            while (br.readLine().also { line = it } != null) {
                sb.append(line).append("\n")
            }
            sb.toString()
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}

object CHUtil {
    private var chUrl = "jdbc:clickhouse://192.168.1.71:8123/default?socket_timeout=3600000"

    fun getConnection(): ClickHouseConnection {
        return ClickHouseDataSource(chUrl).getConnection("default", "123456")
    }

    fun runSql(sql: List<String>) {
        val connection = getConnection()
        sql.forEach { connection.createStatement().executeQuery(it) }

        connection.close()
    }

}

object TimeUtil {
    //毫秒格式化为天小时分钟秒
    fun mmToFormat(milliseconds: Long): String {

        val seconds = milliseconds / 1000
        val minutes = seconds / 60
        val hours = minutes / 60
        val days = hours / 24

        var result = ""
        if(days !=0L){
            result += "${days}天"
        }
        if ((hours % 24) !=0L){
            result +="${hours % 24}小时"
        }

        if((minutes % 60)!=0L){
            result +="${minutes % 60}分钟"
        }
        // todo
        if((seconds % 60)!=0L){
            result+="${seconds % 60}秒"
        }
        if(result == ""){
            result +="0秒"
        }

        return result
    }
}
object FileUtil{

    fun byteToHigher(size:Long):String{
        var stringSize =""
        if(size<1024L){
            stringSize ="$size B"
        }else if(size<(1024L*1024L)){
            stringSize = "${"%.2f".format(size.toDouble()/1024L.toDouble())} KB"
        }else if(size<(1024L*1024L*1024L)){
            stringSize = "${"%.2f".format(size.toDouble()/(1024L*1024L).toDouble())} MB"
        }else{
            stringSize = "${"%.2f".format(size.toDouble()/(1024L*1024L*1024L).toDouble())} GB"
        }
        return stringSize
    }
}

val Any.logger: Logger
    get() = LoggerFactory.getLogger(this.javaClass)

val objectMapper: ObjectWriter = run {
    val format = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    ObjectMapper().apply {
        dateFormat = format
    }.writerWithDefaultPrettyPrinter()
}

fun Any.toJson(): String {
    return objectMapper.writeValueAsString(this)
}
